//
//  OperationQueueShell.m
//  etionLib
//
//  Created by xqls on 12-5-15.
//  Copyright (c) 2012年 GuangZhouXuanWu. All rights reserved.
//

#import "OperationQueueShell.h"

#import "XMSTimerBlock.h"

#import "XMSDataOperationManager.h"

//@implementation COperationQueueShell
//
//static NSOperationQueue *s_operationqueue;
//
//+ (void)InitOperationQueue
//{
//    if (s_operationqueue == nil)
//    {
//        s_operationqueue = [NSOperationQueue new];
//        [s_operationqueue setMaxConcurrentOperationCount:7];
//    }
//}
//
//+ (void)ReleaseOperationQueue
//{
//    [s_operationqueue cancelAllOperations];
//    if ([NSThread isMainThread] == NO)
//        while ([s_operationqueue operationCount]);
//    [s_operationqueue release_mm];
//    s_operationqueue = nil;
//}
//
//+ (void)AddOperation:(id)target sel:(SEL)sel pararm:(id)pararm
//{
//    NSInvocationOperation *invocation = [[NSInvocationOperation alloc] initWithTarget:target selector:sel object:pararm];
//    [s_operationqueue addOperation:invocation];
//    [invocation release_mm];
//}
//
//+ (void)AddOperationWithBlock:(void (^)(void))block
//{
//    [s_operationqueue addOperationWithBlock:block];
//}
//
//+ (void)AddOperations:(NSArray *)ops WaitUntilFinished:(BOOL)wait
//{
//    [s_operationqueue addOperations:ops waitUntilFinished:wait];
//}
//
//@end

void DispatchMainThreadAsync(dispatch_block_t handle)
{
    dispatch_async(dispatch_get_main_queue(), handle);
}

void DispatchMainThreadSync(dispatch_block_t handle)
{
    dispatch_sync(dispatch_get_main_queue(), handle);
}

void DispatchMainThreadSyncAfterDelay(NSTimeInterval nInterval, dispatch_block_t handle)
{
    void(^fun)() = ^
    {
        [[[[XMSTimerBlock alloc] initTimerWithTimeInterval:0 repeats:NO block:^(XMSTimerBlock *timer)
        {
            handle();
        }] autorelease_mm] setFireDateFromNowToTimeInterval:nInterval];
    };
    if ([NSThread isMainThread] == YES)
    {
        fun();
    }
    else
    {
        DispatchMainThreadSync(^
        {
            fun();
        });
    }
}

void DispatchMainThread(BOOL bWaitunitdone, dispatch_block_t handle)
{
    if ([NSThread isMainThread] == YES)
    {
        handle();
    }
    else
    {
        if (bWaitunitdone == NO)
            DispatchMainThreadAsync(handle);
        else
            DispatchMainThreadSync(handle);
    }
}

void DispatchThread(dispatch_block_t handle)
{
    if ([NSThread isMainThread] == YES)
    {
        DispatchGlobalThreadAsync(handle);
    }
    else
    {
        handle();
    }
}

void DispatchGlobalThreadAsync(dispatch_block_t handle)
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), handle);
}

void DispatchQueueThread(dispatch_queue_t queue,const void *key, BOOL bWaitunitdone, dispatch_block_t handle)
{
    if (dispatch_get_main_queue() == queue)
    {
        if (bWaitunitdone == NO)
            dispatch_async(queue, handle);
        else
            handle();
    }
    else
    {
        void *v = dispatch_get_specific(key);
        if (v != NULL || queue == dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))
        {
            if (bWaitunitdone == NO)
                dispatch_async(queue, handle);
            else
                handle();
        }
        else
        {
            if (bWaitunitdone == NO)
                dispatch_async(queue, handle);
            else
                dispatch_sync(queue, handle);
        }
    }
}

void DispatchMainThreadQueue(dispatch_queue_t queue,const void *key,BOOL bWaitunitdone, dispatch_block_t handle)
{
    if ([NSThread isMainThread] == YES)
    {
        handle();
    }
    else
    {
        if (bWaitunitdone == NO)
            dispatch_async(queue, handle);
        else
        {
            void *v = dispatch_get_specific(key);
            if (v == NULL && queue != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))
                dispatch_sync(queue, handle);
            else
                handle();
        }
    }
}

void DispatchThreadSync(dispatch_queue_t queue, const void *key, dispatch_block_t handle)
{
    void *v = dispatch_get_specific(key);
    if (v == NULL && queue != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))
        dispatch_sync(queue, handle);
    else
        handle();
}

void DispatchThreadGroup(NSArray *arGrouphandle)
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    [arGrouphandle enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
    {
        dispatch_group_async(group, queue, obj);
    }];
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    dispatch_release_mm(group);
}

void DispatchThreadMultiTask(EDispatchThreadMultiTaskRunType type,NSUInteger groupCount,NSArray* arTaskblock,void(^isNeedContuinue)(NSUInteger taskInindex,NSInteger nResult,BOOL *stop))
{
    switch(type)
    {
        case EDispatchThreadMultiTaskRunTypeQueue:
        {
            for(NSUInteger i=0;i<arTaskblock.count;i++)
            {
                @autoreleasepool
                {
                    __block NSInteger nResult = FALSE;
                    NSInteger(^task)() = [arTaskblock objectAtIndex:i];
                    DispatchThread(^
                    {
                        nResult = task();
                    });
                    BOOL stop = NO;
                    isNeedContuinue(i,nResult,&stop);
                    if(stop == YES)
                        break;
                }
            }
            break;
        }
        case EDispatchThreadMultiTaskRunTypeGroup:
        {
            NSUInteger n = arTaskblock.count/groupCount+(arTaskblock.count%groupCount==0?0:1);
            for(NSUInteger i=0;i<n;i++)
            {
                @autoreleasepool
                {
                    NSArray *ar = [arTaskblock subarrayWithRange:NSMakeRange(i*groupCount, i<n-1?groupCount:arTaskblock.count-i*groupCount)];

                    XMSQueueDictionary *qd = [[XMSQueueDictionary new]autorelease_mm];
                    for(NSInteger(^task)() in ar)
                    {
                        XMSNumberInt *nInt = [XMSNumberInt numberIntWithIntValue:0];
                        void(^t)()=Block_copy(^
                        {
                            nInt.intValue = task();
                        });
                        [qd addKvPairDirect:[XMSKvPair kvPairWithKey:t value:nInt]];
                        Block_release(t);
                    }
                    DispatchThreadGroup([qd allKeys]);
                    
                    NSInteger nResult = FALSE;
                    for(XMSNumberInt *nInt in [qd allValues])
                    {
                        if(nInt.intValue == TRUE)
                            nResult = TRUE;
                        else
                            break;
                    }
                    BOOL stop = NO;
                    isNeedContuinue(i,nResult,&stop);
                    if(stop == YES)
                        break;
                }
            }
            break;
        }
    }
}

@implementation XMSDispatchQueueWrapper
{
    dispatch_queue_t _queue;
    const void *_key;
}

@synthesize queue = _queue;
@synthesize key = _key;

-(id)init
{
    if (self = [super init])
    {
        _queue = dispatch_queue_create("",NULL);
        _key = NULL;
    }
    return self;
}

-(id)initWithName:(const char *)name key:(const void*)key
{
    if (self = [super init])
    {
        _queue = dispatch_queue_create(name,NULL);
        _key = key;
        
        if(_key != NULL)
            dispatch_queue_set_specific(_queue, _key, _queue, NULL);
    }
    return self;
}

-(id)initWithName:(const char *)name
{
    if (self = [super init])
    {
        _queue = dispatch_queue_create(name,NULL);
        _key = _queue;
        
        dispatch_queue_set_specific(_queue, _key, _queue, NULL);
    }
    return self;
}

-(void)dealloc
{
    dispatch_release_mm(_queue);
    _key=NULL;
    superdealloc_mm;
}

+(id)dispatchQueueWrapper
{
    return [[[XMSDispatchQueueWrapper alloc]init]autorelease_mm];
}

+(id)dispatchQueueWrapperWithName:(const char *)name
{
    return [[[XMSDispatchQueueWrapper alloc]initWithName:name]autorelease_mm];
}

+(id)dispatchQueueWrapperWithName:(const char *)name key:(const void*)key
{
    return [[[XMSDispatchQueueWrapper alloc]initWithName:name key:key]autorelease_mm];
}

-(void)dispatchThreadSync:(dispatch_block_t)block
{
    DispatchThreadSync(_queue, _key, block);
}

-(void)dispatchThreadAsync:(dispatch_block_t)block
{
    dispatch_async(_queue, block);
}

@end

@interface XLGSingleQueueInternal : XMSDataOperationManager

@end

@implementation XLGSingleQueueInternal

@end

@implementation XMSSingleQueue

static XLGSingleQueueInternal *s_smq;

+ (void)runAsyncBlock:(void (^)())block
{
    static dispatch_once_t once;
    dispatch_once(&once, ^
    {
        if(s_smq == nil)
        s_smq = [XLGSingleQueueInternal new];
    });
    [s_smq requestQueueAsyncBlock:block];
}

+ (void)runSyncBlock:(void (^)())block
{
    static dispatch_once_t once;
    dispatch_once(&once, ^
    {
        if(s_smq == nil)
        s_smq = [XLGSingleQueueInternal new];
    });
    [s_smq requestQueueSyncBlock:block];
}

@end


static XMSStaticVariableQueue *s_svq;

@interface XMSStaticVariableQueue ()
{
    XMSDispatchQueueWrapper *_wapper;
}
@property(nonatomic,readonly) XMSDispatchQueueWrapper *wapper;
@end

@implementation XMSStaticVariableQueue
@synthesize wapper = _wapper;

- (id)init
{
    self = [super init];
    
    _wapper = [[XMSDispatchQueueWrapper alloc]initWithName:"StaticVariableQueue"];
    
    return self;
}

- (void)dealloc
{
    [_wapper release_mm];
    superdealloc_mm;
}

+ (void)accessVariable:(void (^)())block
{
    static dispatch_once_t onceToken = 0;
    if (s_svq == nil)
    {
        dispatch_once(&onceToken, ^
        {
            s_svq = [XMSStaticVariableQueue new];
        });
    }
    [s_svq.wapper dispatchThreadSync:block];
}

+ (void)syncAccessVariable:(void (^)())block
{
    [XMSStaticVariableQueue syncAccessVariable:block];
}

+ (void)asyncAccessVariable:(void (^)())block
{
    static dispatch_once_t onceToken = 0;
    if (s_svq == nil)
    {
        dispatch_once(&onceToken, ^
        {
            s_svq = [XMSStaticVariableQueue new];
        });
    }
    [s_svq.wapper dispatchThreadAsync:block];
}

@end

@implementation XMSWaitingSemaphore
{
    dispatch_semaphore_t _semaphore;
}

-(id)init
{
    self = [super init];
    
    _semaphore = dispatch_semaphore_create(0);
    
    return self;
}

- (void)dealloc
{
    if (_semaphore != NULL)
        dispatch_release_mm(_semaphore);
    _semaphore = NULL;
    superdealloc_mm;
}

- (void)waitingFinish
{
    dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
}

- (void)stopWaiting
{
    if (_semaphore != NULL)
        dispatch_semaphore_signal(_semaphore);
}

+(void)waitUntilSignal:(void(^)(void(^signalFun)()))block
{
    XMSWaitingSemaphore *w=[[XMSWaitingSemaphore new]autorelease_mm];
    void(^s)()=^
    {
        [w stopWaiting];
    };
    block(s);
    [w waitingFinish];
}

@end
